#include <REGX52.H>
#include "IIC.h"
#include "LCD1602.h"
#include "Delay.h"

void LCD1602_Send4Bits(unsigned char Data, bit Mode)
{
    unsigned char DataL = (Data & 0x0f) << 4; // 这会将低4位移到高4位
    unsigned char DataH = Data & 0xf0;        // 这已经是高4位了

    // 这里应该先发送高4位，再发送低4位
    IIC_Start();
    IIC_SendByte(LCD1602_ADDRESS << 1);
    IIC_ReceiveAck();

    // 发送高4位
    IIC_SendByte(DataH | (Mode ? LCD_RS : 0) | LCD_BACKLIGHT | LCD_EN);
    IIC_ReceiveAck();
    IIC_SendByte(DataH | (Mode ? LCD_RS : 0) | LCD_BACKLIGHT);
    IIC_ReceiveAck();

    // 发送低4位
    IIC_SendByte(DataL | (Mode ? LCD_RS : 0) | LCD_BACKLIGHT | LCD_EN);
    IIC_ReceiveAck();
    IIC_SendByte(DataL | (Mode ? LCD_RS : 0) | LCD_BACKLIGHT);
    IIC_ReceiveAck();

    IIC_Stop();
}

void LCD1602_WriteCommand(unsigned char Command)
{
    LCD1602_Send4Bits(Command,0);

}

void LCD1602_WriteData(unsigned char Data)
{
    LCD1602_Send4Bits(Data,1);
}

void LCD1602_Init()
{
    Delay(50);

    // 初始化为4位模式
    LCD1602_Send4Bits(0x03, 0); // 发送0x3（高4位）
    Delay(5);
    LCD1602_Send4Bits(0x03, 0); // 再次发送0x3
    Delay(1);
    LCD1602_Send4Bits(0x03, 0); // 第三次发送0x3
    Delay(1);
    LCD1602_Send4Bits(0x02, 0); // 发送0x2，切换到4位模式

    // 设置显示模式：4位，2行，5x8点阵
    LCD1602_WriteCommand(0x28);
    Delay(1);

    // 显示开关控制：显示开，光标关，闪烁关
    LCD1602_WriteCommand(0x0C);
    Delay(1);

    // 清屏
    LCD1602_WriteCommand(0x01);
    Delay(2);

    // 输入模式设置：增量，不移位
    LCD1602_WriteCommand(0x06);
    Delay(1);
}

void LCD1602_SetCursor(unsigned char X,unsigned char Y)
{
    if(X==1){
        LCD1602_WriteCommand(0x80+Y-1);
    }
    else{
        LCD1602_WriteCommand(0xC0+Y-1);
    }
}

void LCD1602_PrintString(unsigned char X,unsigned char Y,unsigned char *String)
{
    LCD1602_SetCursor(X,Y);
    while(*String!='\0'){
        LCD1602_WriteData(*String++);
    }
}

unsigned int pow(unsigned int x,unsigned int y)
{
    unsigned char i;
    unsigned int result=1;
    for(i=0;i<y;i++){
        result*=x;
    }
    return result;
}

void LCD1602_PrintNum(unsigned char X,unsigned char Y,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD1602_SetCursor(X,Y);
    for(i=Length;i>0;i--){
        LCD1602_WriteData(Number/pow(10,i-1)%10+'0');
    }
}

void LCD1602_PrintSignedNum(unsigned char X, unsigned char Y, int Number, unsigned char Length)
{
    unsigned char i;
    LCD1602_SetCursor(X, Y);
    if(Number < 0)
    {
        LCD1602_WriteData('-');
        Number = -Number;
        LCD1602_SetCursor(X, Y + 1);
        for (i = Length; i > 0; i--)
        {
            LCD1602_WriteData(Number / pow(10, i - 1) % 10 + '0');
        }
    }
    else if(Number>0)
    {
        LCD1602_WriteData('+');
        LCD1602_SetCursor(X, Y + 1);
        for (i = Length; i > 0; i--)
        {
            LCD1602_WriteData(Number / pow(10, i - 1) % 10 + '0');
        }
    }
    else if(Number==0)
    {
        LCD1602_SetCursor(X, Y);
        for (i = Length; i > 0; i--)
        {
            LCD1602_WriteData(Number + '0');
        }
    }

}

void LCD1602_PrintHexNum(unsigned char X, unsigned char Y, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    LCD1602_SetCursor(X, Y);
    for(i=Length;i>0;i--)
    {
        if (((Number >> ((i - 1) * 4)) & 0x0F) < 10)
        {
            LCD1602_WriteData(((Number >> ((i - 1) * 4)) & 0x0F) + '0');
        }
        else
        {
            LCD1602_WriteData(((Number >> ((i - 1) * 4)) & 0x0F) - 10 + 'A');
        }
    }
}

void LCD1602_PrintBinNum(unsigned char X, unsigned char Y, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    LCD1602_SetCursor(X,Y);
    for(i=Length;i>0;i--)
    {
        LCD1602_WriteData(((Number >> (i-1)) & 0x01) +'0' );
    }
}